| Auxiliary functions

> module Aux (
>   -- * Lists
>   rapp, remove, merge, zipKeep, lookupIx, (!:), map',
>   -- * Misc
>   Hand(..), fact, 
>   -- * Printing
>   MonadPrinter (..)
> ) where

> import qualified Data.List as List
> import Control.Monad.Identity (Identity)


* Lists

| Reverse append: @x ``rapp`` y = reverse x ++ y@

> rapp :: [a] -> [a] -> [a]
> rapp = flip $ foldl $ flip (:)

| Remove the nth element of a list

> remove :: Int -> [a] -> [a]
> remove = r id
>   where r cont 0 (_:xs) = cont xs
>         r cont k (x:xs) = r (cont . (x:)) (k-1) xs 
>         r _  _ []       = error "Aux.remove: index too large"

| A version of zip that keeps remaining elements.

> zipKeep :: (a -> a -> a) -> [a] -> [a] -> [a]
> zipKeep f (x0:x') (y0:y') = f x0 y0 !: zipKeep f x' y'
> zipKeep f [] y = y
> zipKeep f x [] = x

| Looks up an element in an association list and also returns its index.

> lookupIx :: (Eq t) => Int -> t -> [(t, t1)] -> Maybe (Int, t1)
> lookupIx _ _  [] = Nothing
> lookupIx i k' ((k,v):m) | k == k'   = Just (i,v)
>                         | otherwise = lookupIx (i+1) k' m

| Merging two ordered lists

> merge :: Ord a => [a] -> [a] -> [a]
> merge x [] = x
> merge [] y = y
> merge x@(x0:x') y@(y0:y') = 
>   case compare x0 y0 of
>     LT -> x0 : merge x' y
>     GT -> y0 : merge x y'
>     EQ -> x0 : y0 : merge x' y'

| A strict version of map

> map' :: (a -> b) -> [a] -> [b]
> map' f = foldr ((!:) . f) []

| List constructor, strict in both arguments

> (!:) :: a -> [a] -> [a]
> x !: y = x `seq` y `seq` x : y

> infixr 5 !:


* Miscellaneous

| The factorial function. This implementation is memoized.

> fact :: Int -> Integer
> fact = (!!) (let s f k = f : s (k*f) (k+1) in s 1 1)

> data Hand = L | R deriving (Eq,Show)


* Printing

| A monad with printing: use IO to see the output, Identity to turn it
  off.

> class Monad m => MonadPrinter m where
>    print :: String -> m ()
>    printLn :: String -> m ()

> instance MonadPrinter IO where
>    print = putStr
>    printLn = putStrLn

> instance MonadPrinter Identity where
>    print _ = return ()
>    printLn _ = return ()
